﻿#pragma once

#include <mutex>
#include <queue>
#include "Misc/CommonMacros.h"
#include "Containers/Delegate.h"
#include "Containers/ThreadSafePtr.h"
#include "IPAddress.h"

class CTCPClient;
class CSocketPlatformData;

enum class ETCPServerState
{
    Idle, //空闲状态 
    Listening, //正在监听
};

enum class ETCPServerError
{
    CreateSocketError, //创建socket失败
    CreateSocketWhenListeningError, //正在监听时创建socket
    BindAddressAndPortError, //绑定socket失败,地址错误或者端口被占用
    ListenError, //监听失败
};

//TCP服务器，
//由于底层使用到了线程安全的智能指针，
//所以这个类对像也得使用线程安全的智能指针
class WHENGINE_API CTCPServer : public EnableThreadSafeSharedPtrFromThis<CTCPServer>
{
public:
    //创建一个TCP服务器,使用这个函数而非构造函数是为了强制使用线程安全智能指针
    static TThreadSafeSharedPtr<CTCPServer> Create();
    ~CTCPServer();

    //测试端口是否被占用，这个函数可以在任意线程调用
    static bool IsPortOccupied(const SIPAddress& IP,uint16_t Port);

    //开始监听指定的IP和端口,这个函数可以在任意线程调用
    void Listen(const SIPAddress& IP,uint16_t Port);
    //停止监听,这个函数可以在任意线程调用
    void StopListen();
    //是否正在监听,这个函数可以在任意线程调用
    bool IsListening();

    //当有新的客户端连接时触发，由工作线程触发
    TDelegate<void> OnClientConnected;
    //获取下一个待处理的客户端，是个已经连接的socket
    //这个函数可以在任意线程调用
    TThreadSafeSharedPtr<CTCPClient> GetNextPendingClient();
    //当前线程等待直到有新的客户端连接
    void WaitForClientConnected();


    //socket错误事件,当发生错误时触发
    //可能由主线程或者工作线程触发
    TDelegate<void, ETCPServerError> OnErrorOccured;

private:
    CTCPServer();

    //socket和状态的互斥锁
    std::mutex ListenSocketMutex;
    CSocketPlatformData* PlatformData= nullptr;
    ETCPServerState State=ETCPServerState::Idle;


    //已经连接但未处理的socket
    std::mutex PendingAcceptSocketsMutex;
    std::queue<CSocketPlatformData* > PendingAcceptSockets;

    //开始接受连接任务
    void StartAcceptTask();
};